# -*- encoding=UTF-8 -*-
from time import sleep
import serial,threading
import re
import os
import traceback
import json
import requests
from datetime import datetime
from datetime import timedelta
# import threading
import uiautomator2 as u1
# d = u1.connect('R5CR11R7GBZ')
#com_name = "COM4"
from urllib.parse import urljoin
import configparser
space2url ={
    "jwtime1":"http://tangjw.xyz",
    "x":"123"
}
def up2qiniu(local_img,space_name,img_name):
    """
    本图图片的上传
    :param local_img: 本地图片路径
    :param space_name: 云服务器的空间名称
    :param img_name: 上传后的网络上保存的图片名称
    :return img_url: 远程图片的路径(绝对路径)
    """

    from qiniu import Auth, put_file, etag
    import qiniu.config

    access_key = 'YX6Pck4xl_IXjhy9Oay7SsTB_d_XXyCrGlnnvTX7'
    secret_key = 'DQNnoew9MuGzXV3s6BL5B5BD711IQHcEQwhtnMww'

    # 构建鉴权对象
    q = Auth(access_key, secret_key)

    # 要上传的空间
    bucket_name = 'jwtime1'

    # 上传后保存的文件名
    key = img_name

    # 生成上传 Token，可以指定过期时间等
    token = q.upload_token(bucket_name, key, 3600)

    # 要上传文件的本地路径
    # localfile = r'D:\jw8'

    ret, info = put_file(token, key, local_img)
    # print(info)
    # assert ret['key'] == key
    # assert ret['hash'] == etag(local_img)

    # img_url = 空间名称 拼接 远程图片名称
    # img_url = urljoin("http://q57wyk04l.bkt.clouddn.com", img_name)
    img_url = urljoin(space2url[space_name], img_name)
    return img_url

class SerialConnect:
    def __init__(self,com_name):
        self.com_name = com_name
        self.ser = serial.Serial(self.com_name, 115200,timeout=0.5)
        # 设置超时
        # self.ser.timeout = 0.1  # 读超时设置
        # self.ser.writeTimeout = 0.1  # 写超时

    def ser_ready(self):
    # print (ser.isOpen())

        sleep(5)
        if self.ser.isOpen():
            sleep(5)
            self.ser.write("\r\n".encode("utf-8"))
            self.ser.write("root\r\n".encode("utf-8"))
            # ser.write("\r\n".encode("utf-8"))
            sleep(2)
            self.ser.write("\r\n".encode("utf-8"))
            self.ser.write("cp -rdf /mnt/disc1/device.config /rom\r\n".encode("utf-8"))
            sleep(2)
            self.ser.write('reboot\r\n'.encode("utf-8"))
            sleep(40)
            self.ser.write("\r\n".encode("utf-8"))
            self.ser.write("root\r\n".encode("utf-8"))

            sleep(2)
            self.ser.write("\r\n".encode("utf-8"))
            self.ser.write("cp -rf /ipc/bin/ipc_updater.sh /mnt/ramdisk\r\n".encode("utf-8"))

            sleep(2)
            self.ser.write("\r\n".encode("utf-8"))
            self.ser.write("/mnt/ramdisk/ipc_updater.sh /mnt/disc1/oppo_t31x_upg.bin\r\n".encode("utf-8"))

            # sleep(10)
            # self.ser.write("\r\n".encode("utf-8"))
            # self.ser.write("/ipc/bin/oppo_t31_upg /mnt/disc1/oppo_t31x_upg.bin\r\n".encode("utf-8"))

            sleep(100)

        else:
            print ('串口连接错误')

    def ser_log(self):
        # with open('logdata.txt', "a") as f:  # 设置文件对象
        return str(self.ser.readline()).replace('b','')

    def ser_alllog(self,config):
        #
        global all_log
        all_log = []
        while True:  # 循环接收数据
            config.read(cfgpath, encoding="utf-8")
            video_camera_name = config.get('sec1', '是否结束获取LOG')
            print(video_camera_name)
            sleep(1)
            print(self.ser.inWaiting())
            while self.ser.inWaiting() > 0:  # 当接收缓冲区中的数据不为零时，执行下面的代码
                # sleep(3)
                read_log = str(self.ser.read(self.ser.inWaiting())).split('\\r\\n')
                print(read_log)
                for read_i in range(0,len(read_log)):
                    all_log.append(read_log[read_i])
            print('是否在外面')
            if video_camera_name == '是':
                break
            print ('all_log类型',type(all_log))
        #self.ser_write(all_log)

    def ser_write(self,alllog_list):
        dt3 = datetime.now().strftime('%Y-%m-%d_%H.%M.%S')
        file = dt3 + ".txt"

        for i in range(0, len(alllog_list)):
            with open(file, 'a') as f:
                f.write(str(alllog_list[i]) + "\n")
        # f.close()
        robot_log_singleurl = up2qiniu(file, "jwtime1", file)
        # os.remove(robot_log_file)
        return robot_log_singleurl

class Template_mixin(object):
    """html报告"""
    HTML_TMPL = """
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>自动化测试报告</title>
            <link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
            <h1 style="font-family: Microsoft YaHei">自动化测试报告</h1>
            <p class='attribute'><strong>测试人员 : </strong> 钉钉机器人</p>
            <p class='attribute'><strong>开始时间 : </strong> %(startTime)s</p>
            <p class='attribute'><strong>合计耗时 : </strong> %(totalTime)s</p>
            <p class='attribute'><strong>测试结果 : </strong> %(value)s</p>
            <style type="text/css" media="screen">
        body  { font-family: Microsoft YaHei,Tahoma,arial,helvetica,sans-serif;padding: 20px;}
        </style>
        </head>
        <body>
            <table id='result_table' class="table table-condensed table-bordered table-hover">
                <colgroup>
                    <col align='left' />
                    <col align='right' />
                    <col align='right' />
                    <col align='right' />
                </colgroup>
                <tr id='header_row' class="text-center success" style="font-weight: bold;font-size: 14px;">
                    <th>第N次</th>
                    <th>测试结果</th>
                    <th>开始升级时间</th>
                    <th>升级完成时间</th>
                    <th>升级耗时</th>
                    <th>失败原因</th>
                </tr>
                %(table_tr)s
            </table>
        </body>
        </html>"""

    TABLE_TMPL = """
        <tr class='failClass warning'>
            <td>%(step)s</td>
            <td>%(result)s</td>
            <td>%(start_s)s</td>
            <td>%(start_e)s</td>
            <td>%(take_e)s</td>
            <td>%(reason)s</td>
        </tr>"""




class DingMessage:
    def __init__(self):
        #self.URL = "https://oapi.dingtalk.com/robot/send?access_token=442ba2d17c80a18c240779d630735ed46cf42c9741901907e5d00ce913e595cc"  # Webhook地址
        self.URL = "https://oapi.dingtalk.com/robot/send?access_token=748649e1116ff3123984bfb4c03b5f24c21d369ab2e6bd580b4f64bdede837c5"  # Webhook地址
        self.headers = {'Content-Type':'application/json'}

    def dingtalk_testexception(self,i,cameras_log,result_url):
        data_dict = {
            "msgtype": "markdown",

            "markdown": {
                "title": "升级压力测试异常提示",
                "text": "#### **<font color=#FF0000>第"+str(i)+"次测试异常**</font>\n\n"
                        "[查看摄像头设备LOG](" + cameras_log + ')\n\n'
                        "[查看报错时截图](" + result_url + ')'
            }
        }

        json_data = json.dumps(data_dict)
        response = requests.post(self.URL, data=json_data, headers=self.headers, timeout=3)

    def dingtalk_testpass(self,i,start_time,end_time,take_time):
        data_dict = {
            "msgtype": "markdown",

            "markdown": {
                "title": "升级压力测试通过提示",
                "text": "#### **<font color=#7CFCOO>第"+str(i)+"次测试通过**</font>\n\n"
                        "> **开始升级时间:** <font color=#000000>" + start_time + "</font>\n\n"
                        "> **升级完成时间:** <font color=#000000>" + end_time + "</font>\n\n"
                        "> **升级消耗时长:** <font color=#000000>" + take_time + "</font>\n\n"
            }
        }
        json_data = json.dumps(data_dict)
        response = requests.post(self.URL, data=json_data, headers=self.headers, timeout=3)

    def dingtalk_robot(self, total, pass_total, fial_total, report_url):
        data_dict = {
            "msgtype": "markdown",

            "markdown": {
                "title": "测试报告",
                "text": "#### 测试报告 \n\n"
                        "![report](http://tangjw.xyz/test_report.png)"
                        "> **执行次数:** **" + str(total) + "**\n\n"
                                                        "> **PASS:** **<font color=#7CFCOO>" + str(
                    pass_total) + "</font>**\n\n"
                                  "> **FAIL:** **<font color=#FF0000>" + str(fial_total) + "</font>**\n\n"
                                                                                           "[查看详情]" + report_url
            }
        }

        json_data = json.dumps(data_dict)
        response = requests.post(self.URL, data=json_data, headers=self.headers, timeout=3)


class OperationDevices:
    def __init__(self,devices_name):
        self.d = u1.connect(devices_name)
        self.d.unlock()
        self.d.watcher.when("忽略此设备").click()
        self.d.watcher.when("立即升级").press('back')
        # self.d.watcher.when("检测到新版本").press('back')
        self.d.watcher.start()

    def devices_up(self):
        # self.d.unlock()
        # self.d.watcher.when("忽略此设备").click()
        # self.d.watcher.when("检测到新版本").press('back')
        # self.d.watcher.start()

        self.d.app_start('com.heytap.smarthome')
        gotimes = 0
        while True:
            if self.d(text="首页").exists:
                sleep(3)
                break
            else:
                sleep(3)
                gotimes += 1
            if gotimes == 5:
                break
        godevices = 0
        while True:
            self.d.swipe_ext("down", scale=0.8)
            sleep(3)
            self.d(resourceId="com.heytap.smarthome:id/tv_label").click(timeout=5)
            if self.d(resourceId="com.heytap.camera.gwell:id/live_videoview_container").wait(timeout=5):
                break
            else:
                sleep(1)
                godevices += 1
            if godevices == 5:
                break
        self.d.xpath('//androidx.appcompat.widget.LinearLayoutCompat').click(timeout=5)
        self.d(text="固件版本").click(timeout=5)
        self.d(text="升级").click(timeout=5)
        start_time = datetime.now()
        assert self.d(text="升级成功").wait(timeout=200),'升级不成功'
        end_time = datetime.now()
        total_time = end_time - start_time
        return str(start_time),str(end_time),str(total_time)

    def quit_app(self):
        for quit_n in range(2):
            sleep(1)
            if self.d(text="首页").exists:
                break
            else:
                self.d.press("back")
        self.d.app_stop('com.heytap.smarthome')

    def re_online(self):
        # self.d.unlock()
        # self.d.watcher.when("忽略此设备").click()
        # self.d.watcher.when("检测到新版本").press('back')
        # self.d.watcher.start()

        self.d.app_start('com.heytap.smarthome')
        gotimes = 0
        while True:
            if self.d(text="首页").exists:
                sleep(3)
                break
            else:
                sleep(3)
                gotimes += 1
            if gotimes == 4:
                break
        godevices = 0
        while True:
            self.d.swipe_ext("down", scale=0.8)
            sleep(3)
            if self.d(text="在线").wait(timeout=5):
                break
            else:
                godevices += 1
            if godevices == 30:
                break
        assert self.d(text="在线").wait(timeout=5),'设备不在线'


if __name__ == '__main__':
    print ('注：\n1、手机开发者模式中打开不锁定屏幕，充电时不会休眠\n2、智能家居APP中只添加测试的设备')
    com_name = input("输入摄像头连接端口号（例如：COM1）：")
    devices_name = input("输入连接的手机设备名(输入adb devices查看)：")
    times = input("输入测试次数(输入整数数字，最小1)：")
    # com_name = "COM4"  # "COM4"
    # devices_name = 'R5CR11R7GBZ'
    # times = '1'
    # print (type(times))

    cfgpath = "dbconf.ini"
    config = configparser.ConfigParser()
    config.read(cfgpath, encoding="utf-8")

    count_success = 0
    start_time = datetime.now()
    # devices_name = 'R5CR11R7GBZ'
    op = OperationDevices(devices_name)
    # op.re_online()
    # op.devices_up()
    # op.quit_app()
    sleep(5)
    file = 'log_data.txt'
    i = 0
    timer = []
    report_message = {}
    test_result = None
    while i < int(times):
        list_result = []
        w_report = ''
        i = i + 1
        timer = None
        print(('Testing time: %d') % (i))

        video_reset = config.get('sec1', '是否结束获取LOG')
        if video_reset == '是':
            config.set("sec1", '是否结束获取LOG', '否')
            config.write(open("dbconf.ini", "w"))
        alllog_list = []
        #摄像头准备降版本
        try:
            serial_devices = SerialConnect(com_name)
            serial_devices.ser_ready()
            sleep(2)
        except:
            pass
        try:
            t1 = threading.Thread(target=serial_devices.ser_alllog, args=(config,))
            t1.start()
            # op.re_online()
            # op.quit_app()
            #print ('star123')
            sleep(3)
            timer = op.devices_up()
            op.quit_app()
            #
            #alllog_list = serial_devices.ser_alllog()
            #serial_devices.ser_write(alllog_list)
            test_result = '<font color="green">PASS</font>'
            count_success = count_success + 1
        except Exception as err:
            # a1 = traceback.format_exc()
            # print(a1)
            #alllog_list = serial_devices.ser_alllog()
            #cameras_log = serial_devices.ser_write(alllog_list)
            test_result = '<font color="red">FAIL</font>'
            try:
                dt1 = datetime.now()
                dt2 = dt1.strftime('%Y-%m-%d_%H.%M.%S')
                image = dt2 + ".png"
                op.d.screenshot(image)
                res = up2qiniu(image, "jwtime1", image)
                # os.remove(image)
            except:
                res = "获取链接失败"
            a1 = traceback.format_exc()
            print(a1)
            # pos1 = a1.find('in jwt')
            # pos2 = a1.find('\n', pos1 + 10)
            # pos_1 = a1[pos1 - 23:pos2]
            # pos3 = re.sub('\n', "", pos_1)
            # w_report += '<a href=' + res + '>查看报错图片</a>' + '<br />'  # '<a href='+res+'>图片</a>'
            # w_report += '<a href=' + cameras_log + '>查看摄像头日志</a>'  # '<a href='+res+'>图片</a>'
            # sleep(3)

            config.set("sec1", '是否结束获取LOG', '是')
            config.write(open("dbconf.ini", "w"))
            video_camera_name = config.get('sec1', '是否结束获取LOG')
            if video_camera_name == '是':
                print('上传LOG')
                #alllog_list = serial_devices.ser_alllog()
                cameras_log = serial_devices.ser_write(all_log)

                w_report += '<a href=' + res + '>查看报错图片</a>' + '<br />'  # '<a href='+res+'>图片</a>'
                w_report += '<a href=' + cameras_log + '>查看摄像头日志</a>'  # '<a href='+res+'>图片</a>'
                sleep(3)
            try:
                DingMessage().dingtalk_testexception(i,cameras_log,res)
            except:
                pass
        try:
            if timer != None:
                DingMessage().dingtalk_testpass(i, timer[0], timer[1],timer[2])
        except:
            pass
        op.quit_app()
        serial_devices.ser.close()
        if  test_result == '<font color="green">PASS</font>':
            list_result.append(test_result)
            list_result.append(timer[0])
            list_result.append(timer[1])
            list_result.append(timer[2])
            list_result.append('')

            report_message[i] = list_result
        elif test_result == '<font color="red">FAIL</font>':
            list_result.append(test_result)
            list_result.append('None')
            list_result.append('None')
            list_result.append('None')
            list_result.append(w_report)

            report_message[i] = list_result
        else:
            list_result.append(test_result)
            list_result.append('')
            list_result.append('')
            list_result.append('')
            list_result.append('')
            report_message[i] = list_result

    # 报告详情
    report_time = datetime.now().strftime('%Y-%m-%d_%H.%M.%S')
    report_file = report_time + ".html"
    total_time = datetime.now() - start_time

    # html报告
    start_times = '2022-04-30_15:15'
    end_times = '2022-04-30_15:15'
    take_times = '2022-04-30_15:15'
    table_tr0 = ''
    res = 'http://tangjw.xyz/2022-05-24_18.52.21.png'
    err_reason = '<a href=' + res + '>查看报错图片</a>' + '<br />'+'<a href=' + res + '>查看报错日志</a>' + '<br />'
    html = Template_mixin()
    for n in report_message.keys():
        table_td = html.TABLE_TMPL % dict(
            step=str(n),
            result= report_message[n][0],  # <font color="red"> </font>
            start_s = report_message[n][1],
            start_e = report_message[n][2],
            take_e = report_message[n][3],
            reason= report_message[n][4]
        )
        table_tr0 += table_td
    total_str = '总测试次数 %s，通过 %s，失败 %s，通过率 %s' % (
        times, str(count_success), str(int(times)-count_success),
        str(round(count_success / int(times), 2) * 100) + '%')

    output = html.HTML_TMPL % dict(
        value=total_str,
        table_tr=table_tr0,
        startTime=start_time,
        totalTime=total_time,
    )

    # 生成html报告

    with open(report_file, 'wb') as f:
        f.write(output.encode('utf-8'))

    report_url = '(' + up2qiniu(report_file, "jwtime1", report_file) + ')'
    os.remove(report_file)

    DingMessage().dingtalk_robot(times, str(count_success), str(int(times)-count_success), report_url)
